﻿using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

/*
 * 1、定义自己的事件参数包 class
 * 2、将EventHandler 特化成传输参数包的委托类型
 * 3、响应方法中，将事件参数包类型替换成自己的参数包类型 
 * 
 */

namespace SeniorEvent
{
    class MyEventArgs
    {
        public string text = "";
        public int numer = 0;
        public bool flag = false;

    }

    class player
    {
        public event EventHandler<MyEventArgs> TestEvent;

        public event EventHandler OnAttack;
        public event EventHandler OnException;

        public void DoTest(MyEventArgs myEvent)
        {
            if (TestEvent != null)
            {
                TestEvent(this, myEvent);
            }

        }

        public void DoAOE()
        {
            if (OnAttack != null)
            {
                EventArgs args = new EventArgs();
                OnAttack(this, args);
            }

        }

        public void DoException()
        {
            if (OnException != null)
            {
                EventArgs args = new EventArgs();
                OnException(this, args);
            }
        }

    }

    class Enemy
    {
        public void AttackMe(object sender, EventArgs args)
        {
            try
            {
                Console.WriteLine("好痛啊，敌人攻击我了");
            }
            catch (Exception ex)
            {

            }
        }
    }

    class Excepion
    {
        public void PrintInfo(object sender, EventArgs args)
        {
            Console.WriteLine("有异常了");
        }
    }

    class Test
    {

        public void TestInfo(object sender, MyEventArgs args)
        {
            Console.WriteLine("测试一下参数" + args.text);
        }
    }

    class InputArgs
    {

        public char input;
    }

    class InputManager
    {
        public event EventHandler<InputArgs> OnInput;

        public void WaitForInput()
        {
            while (true)
            {
                char input = Convert.ToChar(Console.Read());
                Console.WriteLine(input);
                if (OnInput != null)
                {
                    InputArgs inputArgs = new InputArgs();
                    inputArgs.input = input;
                    OnInput(this, inputArgs);
                }
            }
        }


    }


    class Program
    {
        public delegate int myDelegate(int i);

        public static int GetName(int i)
        {
            return i + 1;
        }

        public static decimal GetTotal(Func<int, int, decimal> func, int a, int b)
        {
            return func(a, b);
        }

        public static void MultiplyByTwo(double v)
        {
            double result = v * 2;
            Console.WriteLine($"传值：{v}；MultiplyByTwo结果为{result}");
        }
        public static void Square(double v)
        {
            double result = v * v;
            Console.WriteLine($"传值：{v}；Square结果为{result}");
        }

        public static void Debug(string message, Action RegistedProperties)
        {
            RegistedProperties();
            // log.Debug(message);
            OnNotice?.Invoke($"系统异常，请及时处理，异常信息：{message}");
        }

        public static void Notice(string message)
        {
            Console.WriteLine($"通知内容为{message}");
        }

        //声明一个通知的委托
        public delegate void NoticeEventHander(string message);
        //在委托的机制下我们建立以个通知事件
        public static event NoticeEventHander OnNotice;

        /// <summary>
        /// 执行动作:耗时而已
        /// </summary>
        private static void TestThread2(string threadName1, string threadName2)
        {
            Console.WriteLine("线程开始：线程名为：{2}和{3}，当前线程的id为:{0}，当前时间为：{1},", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);
            long sum = 0;
            for (int i = 1; i < 999999999; i++)
            {
                sum += i;
            }
            Console.WriteLine("线程结束：线程名为：{2}和{3}，当前线程的id为::{0}，当前时间为：{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);
        }

        public static void OnKeyInput(object sender, InputArgs inputArgs)
        {
            Console.WriteLine($"收到了:{inputArgs.input}");
        }

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FrmMain());
        }

        static void Main_Old(string[] args)
        {
            InputManager input = new InputManager();
            input.OnInput += OnKeyInput;
            input.WaitForInput();


            Action<string, string> myFunc = TestThread2;
            for (int i = 0; i < 5; i++)
            {
                string name = $"name:{i}";
                myFunc?.Invoke(name, name);
            }


            //注册方式一
            OnNotice += Notice;
            //注册方式二
            //PFTLog.OnNotice += new PFTLog.NoticeEventHander(Notice);

            Debug("测试扩展字段", () =>
            {
                LogicalThreadContext.Properties["LogType"] = "扩展字段内容";
            });



            Debug("测试扩展字段", () =>
            {
                LogicalThreadContext.Properties["LogType"] = "扩展字段内容";
            });


            Action<double> operations = MultiplyByTwo;
            operations(1);
            operations += Square;
            operations(2);



            //var total = GetTotal((a, b) => { return (decimal)a + b; }, 1, 2);
            //Console.WriteLine($"结果为{total}");


            myDelegate myDelegate = new myDelegate(GetName);
            var a = myDelegate(100);// myDelegate.Invoke(10);

            player player = new player();

            Enemy enemy = new Enemy();
            player.OnAttack += enemy.AttackMe;
            player.DoAOE();

            Excepion excepion = new Excepion();
            player.OnException += excepion.PrintInfo;
            player.DoException();

            Test test = new Test();
            player.TestEvent += test.TestInfo;
            MyEventArgs myEvent = new MyEventArgs();
            myEvent.text = "test";
            myEvent.numer = 100;
            player.DoTest(myEvent);

        }

    }



    class Delegate
    {
        public delegate void MyNoReturnNoParaDelegate();//无参数无返回值委托
        public delegate void MyNoReturnWithParaDelegate(int x, int y);//带参无返回值委托
        public delegate int MyWithReturnWithParaDelegate(int x, int y);//带参有返回值委托

        private void NoReturnNoParaMethod()
        {
            Console.WriteLine("This is NoReturnNoParaMethod");
        }

        private void NoReturnWithParaMethod(int x, int y)
        {
            Console.WriteLine($"This is NoReturnWithParaMethod Para1:{x},Para2:{y}");
        }

        private int WithReturnWithParaMethod(int x, int y)
        {
            Console.WriteLine($"This is WithReturnWithParaMethod Para1:{x},Para2:{y}");
            return x + y;
        }

        private void InitDelegate()
        {
            MyNoReturnNoParaDelegate myNoReturnNoParaDelegate = new MyNoReturnNoParaDelegate(NoReturnNoParaMethod);
            MyNoReturnWithParaDelegate myNoReturnWithParaDelegate = NoReturnWithParaMethod;// new MyNoReturnWithParaDelegate(NoReturnWithParaMethod);
            MyWithReturnWithParaDelegate myWithReturnWithParaDelegate = WithReturnWithParaMethod;//可以省去new
                                                                                                 //使用Invoke委托中所引用的方法
            myNoReturnNoParaDelegate.Invoke();
            myNoReturnWithParaDelegate.Invoke(1, 2);
            int sum = myWithReturnWithParaDelegate(1, 2);//也可以省去Invoke
        }
    }

}
